package com.maserb.monitor.service.remote.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.maserb.monitor.common.HttpUtil;
import com.maserb.monitor.common.PageRequestParam;
import com.maserb.monitor.entity.JwOrgEntity;
import com.maserb.monitor.entity.UserEntity;
import com.maserb.monitor.entity.card.EcCardEntity;
import com.maserb.monitor.entity.card.RechargeRecordEntity;
import com.maserb.monitor.entity.schoolNotice.SchoolNoticeEntity;
import com.maserb.monitor.entity.schoolStudent.SchoolStudentEntity;
import com.maserb.monitor.model.OnDutyModel;
import com.maserb.monitor.model.TransactionModel;
import com.maserb.monitor.repository.UserRepository;
import com.maserb.monitor.repository.schoolNotice.SchoolNoticeRepository;
import com.maserb.monitor.repository.schoolStudent.EcCardRepository;
import com.maserb.monitor.repository.schoolStudent.RechargeRecordRepository;
import com.maserb.monitor.repository.schoolStudent.SchoolStudentRepository;
import com.maserb.monitor.service.base.impl.JpaSpecificationServiceImpl;
import com.maserb.monitor.service.remote.EcCardService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
public class EcCardServiceImpl  extends JpaSpecificationServiceImpl<RechargeRecordRepository,
        RechargeRecordRepository, RechargeRecordEntity, String> implements EcCardService {

    @Value("${ecCard.appId}")
    private String appId;

    @Value("${ecCard.appSecret}")
    private String appSecret;

    @Value("${ecCard.url}")
    private String url;

    @Autowired
    SchoolStudentRepository studentRepository;
    @Autowired
    EcCardRepository ecCardRepository;
    @Autowired
    RechargeRecordRepository rechargeRecordRepository;
    @Autowired
    UserRepository userRepository;

    @Override
    public Long doAddOrg(JwOrgEntity org) {
        Map<String, String> params = new HashMap<>();

        params.put("name", org.getName());
        if(org.getParent() == null || org.getParent().getDid() == null) {
            params.put("parentDid", "10000");
        } else {
            params.put("parentDid", org.getParent().getDid().toString());
        }

        String result = HttpUtil.getPostData(url + "addOrg", params);
        JSONObject obj = JSON.parseObject(result);
        if(obj.getBoolean("success")) {
            return obj.getLong("data");
        }

        return 0L;
    }

    @Override
    public void doUpdateOrg(JwOrgEntity org) {
        Map<String, String> params = new HashMap<>();

        params.put("did", org.getDid().toString());
        params.put("name", org.getName());
        if(org.getParent() == null || org.getParent().getDid() == null) {
            params.put("parentDid", "10000");
        } else {
            params.put("parentDid", org.getParent().getDid().toString());
        }

        String result = HttpUtil.getPostData(url + "updateOrg", params);
        log.info(result);
    }

    @Override
    public void doDeleteOrg(JwOrgEntity org) {
        Map<String, String> params = new HashMap<>();
        params.put("did", org.getDid().toString());
        HttpUtil.getPostData(url, params);
    }

    @Override
    public Long doAddPerson(SchoolStudentEntity student) {
        Map<String, String> params = new HashMap<>();

        params.put("studentId", student.getStudentId());
        params.put("name", student.getName());
        if(student.getDid() != null) {
            params.put("did", student.getDid().toString());
        } else {
            params.put("did", "10000");
        }

        params.put("sex", StringUtils.isNotBlank(student.getSex())?student.getSex():"");
        params.put("idcard", StringUtils.isNotBlank(student.getIdcard())?student.getIdcard():"");
        params.put("phoneNumber", StringUtils.isNotBlank(student.getPhoneNumber())?student.getPhoneNumber():"");
        params.put("description", StringUtils.isNotBlank(student.getDescription())?student.getDescription():"");

        String result = HttpUtil.getPostData(url + "addPerson", params);
        JSONObject obj = JSON.parseObject(result);
        if(obj.getBoolean("success")) {
            return obj.getLong("data");
        }

        return 0L;
    }

    @Override
    public Long doAddTeacher(UserEntity teacher) {
        Map<String, String> params = new HashMap<>();

        //接口统一当学生处理，老师用username作为人员编号
        params.put("studentId", teacher.getUserName());
        params.put("name", teacher.getRealName());
        if(teacher.getDid() != null) {
            params.put("did", teacher.getDid().toString());
        } else {
            params.put("did", "10000");
        }

        params.put("sex", StringUtils.isNotBlank(teacher.getSex())?teacher.getSex():"");
        params.put("idcard", StringUtils.isNotBlank(teacher.getIdcard())?teacher.getIdcard():"");
        params.put("phoneNumber", StringUtils.isNotBlank(teacher.getPhoneNumber())?teacher.getPhoneNumber():"");
        params.put("description", StringUtils.isNotBlank(teacher.getDescription())?teacher.getDescription():"");

        String result = HttpUtil.getPostData(url + "addPerson", params);
        JSONObject obj = JSON.parseObject(result);
        if(obj.getBoolean("success")) {
            return obj.getLong("data");
        }

        return 0L;
    }

    @Override
    public void doUpdatePerson(SchoolStudentEntity student) {
        Map<String, String> params = new HashMap<>();

        if(null==student.getCid()){
            params.put("cid", null);
        }else{
            params.put("cid", student.getCid().toString());
        }
        if(null==student.getDid()){
            params.put("did", null);
        }else{
            params.put("did", student.getDid().toString());
        }
        params.put("studentId", student.getStudentId());
        params.put("name", student.getName());
        params.put("sex", StringUtils.isNotBlank(student.getSex())?student.getSex():"");
        params.put("idcard", StringUtils.isNotBlank(student.getIdcard())?student.getIdcard():"");
        params.put("phoneNumber", StringUtils.isNotBlank(student.getPhoneNumber())?student.getPhoneNumber():"");
        params.put("description", StringUtils.isNotBlank(student.getDescription())?student.getDescription():"");

        String result = HttpUtil.getPostData(url + "updatePerson", params);
        log.info(result);
    }

    @Override
    public void doUpdateTeacher(UserEntity teacher) {
        Map<String, String> params = new HashMap<>();
        if(null==teacher.getCid()){
            params.put("cid", null);
        }else{
            params.put("cid", teacher.getCid().toString());
        }
        if(null==teacher.getDid()){
            params.put("did", null);
        }else{
            params.put("did", teacher.getDid().toString());
        }

        params.put("studentId", teacher.getUserName());
        params.put("name", teacher.getRealName());

        params.put("sex", StringUtils.isNotBlank(teacher.getSex())?teacher.getSex():"");
        params.put("idcard", StringUtils.isNotBlank(teacher.getIdcard())?teacher.getIdcard():"");
        params.put("phoneNumber", StringUtils.isNotBlank(teacher.getPhoneNumber())?teacher.getPhoneNumber():"");
        params.put("description", StringUtils.isNotBlank(teacher.getDescription())?teacher.getDescription():"");

        String result = HttpUtil.getPostData(url + "updatePerson", params);
        log.info(result);
    }

    @Override
    public void doDeletePerson(SchoolStudentEntity student) {
        Map<String, String> params = new HashMap<>();
        params.put("cid", student.getCid().toString());
        HttpUtil.getPostData(url, params);
    }

    @Override
    public void doAddRechargeRecord(RechargeRecordEntity rechargeRecord) {
        Map<String, String> params = new HashMap<>();

        params.put("qcls", rechargeRecord.getId());
        if(rechargeRecord.getStudent() != null) {
            params.put("studentId", rechargeRecord.getStudent().getStudentId());
        } else {
            params.put("studentId", rechargeRecord.getTeacher().getTeacherId());
        }
        params.put("totalAmount", rechargeRecord.getTotalAmount().toString());
        params.put("type", rechargeRecord.getRemarks().equals("微信充值")?"2":" 1");
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        params.put("qdate", fmt.format(rechargeRecord.getCreateTime()));

        String result = HttpUtil.getPostData(url + "addRechargeRecord", params);
        JSONObject obj = JSON.parseObject(result);
        if(obj.getBoolean("success")) {
            Integer resultData = obj.getInteger("data");
            if(resultData == 0) {
                rechargeRecord.setRechargeStatus("1");
                rechargeRecordRepository.save(rechargeRecord);
            }
        }
    }

    /**
     * 查询学生交易记录
     * @param page
     * @param personId 人员id
     * @param type 类型 1：学生 2：老师
     * @return
     */
    @Override
    public List<TransactionModel> queryTransaction(PageRequestParam page, String personId, String type) {
        Map<String, String> params = new HashMap<>();

        String personNumber = "";
        if(StringUtils.isEmpty(type) || type.equals("1")) {
            SchoolStudentEntity student = studentRepository.findById(personId).get();
            personNumber = student.getStudentId();
        } else {
            UserEntity teacher = userRepository.findById(personId).get();
            personNumber = teacher.getTeacherId();
        }

        params.put("studentId", personNumber);
        params.put("page", page.getPage().toString());
        params.put("limit", page.getLimit().toString());

        String result = HttpUtil.getPostData(url + "transactionList", params);
        JSONObject obj = JSON.parseObject(result);
        if(obj.getBoolean("success")) {
            JSONObject resultData = obj.getJSONObject("data");
            if(resultData.getInteger("code") == 0) {
                return convertJSONArrayToList(resultData.getJSONArray("result"), TransactionModel.class);
            }
        }

        return new ArrayList<TransactionModel>();
    }

    @Override
    public String queryBalance(String cid) {
        Map<String, String> params = new HashMap<>();
        params.put("cid", cid);
        String result = HttpUtil.getPostData(url + "studentBalance", params);

        JSONObject obj = JSON.parseObject(result);
        if(obj.getBoolean("success")) {
            return obj.getString("data");
        }

        return "0.00";
    }

    /**
     *
     * @param pageable
     * @param personId 人员id
     * @param type 类型 1：学生 2：老师
     * @return
     */
    @Override
    public Page<RechargeRecordEntity> findAllRechargeRecord(Pageable pageable, String personId, String type) {
        return findAll(getSpecification(personId, type), pageable);
    }

    @Override
    public void saveCard(EcCardEntity card) {
        if(StringUtils.isNotBlank(card.getPersonId())) {
            SchoolStudentEntity student = studentRepository.findFirstByCid(Long.valueOf(card.getPersonId()));
            card.setStudent(student);
        }

        if(StringUtils.isNotBlank(card.getType())) {
            if(card.getType().equals("U")) {
                EcCardEntity dbCard = ecCardRepository.findFirstByCardNumber(card.getCardNumber());
                if(dbCard != null) {
                    dbCard.setState(card.getState());
                }
                ecCardRepository.save(dbCard);

                SchoolStudentEntity student = card.getStudent();
                student.setCardNumber(card.getCardNumber());

                studentRepository.save(student);
            } else if(card.getType().equals("I")) {
                ecCardRepository.save(card);
                SchoolStudentEntity student = card.getStudent();
                student.setCardNumber(card.getCardNumber());

                studentRepository.save(student);
            } else if(card.getType().equals("D")) {
                EcCardEntity dbCard = ecCardRepository.findFirstByCardNumber(card.getCardNumber());
                if(dbCard != null) {
                    ecCardRepository.delete(dbCard);
                }
            }
        }
    }

    private Specification<RechargeRecordEntity> getSpecification(String personId, String type) {
        return (Specification<RechargeRecordEntity>) (root, criteriaQuery, criteriaBuilder) -> {
            ArrayList<Predicate> list = new ArrayList<Predicate>();
            Path<String> pathPayStatus = root.get("payStatus");
            list.add(criteriaBuilder.and(criteriaBuilder.equal(pathPayStatus, "1")));

            if (!StringUtils.isEmpty(personId)) {
                if(StringUtils.isEmpty(type) || type.equals("1")) {
                    Join<RechargeRecordEntity, SchoolStudentEntity> studentJoin = root.join("student", JoinType.LEFT);
                    Path<String> pathStudentId = studentJoin.get("id");
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(pathStudentId, personId)));
                } else {
                    Join<RechargeRecordEntity, UserEntity> teacherJoin = root.join("teacher", JoinType.LEFT);
                    Path<String> pathTeacherId = teacherJoin.get("id");
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(pathTeacherId, personId)));
                }
            }

            return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
        };
    }

    <T> List<T> convertJSONArrayToList(JSONArray jsonArray, Class<T> clazz) {
        List<T> resultList = JSON.parseArray(jsonArray.toJSONString(), clazz);
        return resultList;
    }
}
